/*
 * Copyright (c) www.bugull.com
 */

package com.bugull.farm.core.codec;

import com.bugull.farm.core.cache.PropertiesCache;
import com.bugull.farm.core.crypto.Crypto;
import com.bugull.farm.core.utils.ByteUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

/**
 *
 * @author Frank Wen(xbwen@hotmail.com)
 */
public class DefaultCryptoDecoder extends ByteToMessageDecoder {
    
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        if(in.readableBytes() < PropertiesCache.getInstance().getInt("frame.min.size")){
            return;
        }
        Object decoded = decode(ctx, in);
        if (decoded != null) {
            out.add(decoded);
        }
    }
    
    private Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        ByteBuf frame = ctx.alloc().buffer();
        byte flag = in.getByte(1);
        boolean encrypted = ByteUtil.getBit(flag, 6);
        if(!encrypted){
            frame.writeBytes(in);
        }
        else{
            frame.writeByte(in.readByte());  //PV
            frame.writeByte(in.readByte());  //Flag
            in.readBytes(frame, 6);  //Mac

            int len = in.readUnsignedByte();  //Len
            byte[] encryBytes = new byte[len];
            in.readBytes(encryBytes);
            Crypto crypto = new Crypto("AES","CBC/PKCS5Padding");
            crypto.setIV(PropertiesCache.getInstance().get("default.aes.key").getBytes(PropertiesCache.getInstance().get("charset.utf8")));
            byte[] srcBytes = crypto.decrypt(encryBytes, PropertiesCache.getInstance().get("default.aes.key").getBytes(PropertiesCache.getInstance().get("charset.utf8")));
            frame.writeByte(srcBytes.length);
            frame.writeBytes(srcBytes);
        }
        return frame;
    }

}
